﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace iS3.DAL.SQLSERVER
{

    public class ExternalStorageEngine_TimeSplit: IExternalStorageEngine
    {
        ExternalStorage_TimeSplitParam configParam;
        string _tableNameOrPrefix;

        private SQLConn _SQLConn;

        private Dictionary<string, ExternalStorageRecord> tempCahce = new Dictionary<string, ExternalStorageRecord>();
        public ExternalStorageEngine_TimeSplit(SQLConn SQLConn,string tableNameOrPrefix,string configParam)
        {
            _tableNameOrPrefix = tableNameOrPrefix;
            _SQLConn = SQLConn;
            try
            {
                this.configParam = Newtonsoft.Json.JsonConvert.DeserializeObject<ExternalStorage_TimeSplitParam>(configParam);
            }catch(Exception ex)
            {

            }
        }
        public bool checkIfExist(string tabelName)
        {
            string sql = string.Format("select * from [Project_ExternalStorageRecord] where ([ExternalTableName]='{0}')", tabelName);
            using (SqlConnection conn = new SqlConnection(_SQLConn.getConnectionStr()))
            {
                conn.Open();
                using (SqlCommand sqlCommand = new SqlCommand(sql, conn))
                {
                    sqlCommand.CommandTimeout = 300;
                    SqlDataReader sqlDataReader = sqlCommand.ExecuteReader();
                    DataTable dataTable = new DataTable();
                    dataTable.Load(sqlDataReader);
                    sqlDataReader.Close();

                    return (dataTable.Rows.Count > 0);
                }
            }
        }


        public string getExtTableName<TEntity>(TEntity model) where TEntity : DGBase, new()
        {
            return getExtTableName(model.GetValue(configParam.TimeProperty).ToString());
        }
        public string getExtTableName(string param)
        {
            DateTime dtNow = DateTime.Parse(param);
            DateTime begin = dtNow;
            DateTime end = dtNow;
            int year = dtNow.Year;
            int month = dtNow.Month;
            int day = dtNow.Day;
            int hour = dtNow.Hour;
            switch (configParam.IntervalUnit)
            {
                case "y":
                    begin = new DateTime(year, 1, 1,0,0,0);
                    end = new DateTime(year + 1, 1, 1, 0, 0, 0).AddSeconds(-1);
                    break;
                case "m":
                    begin = new DateTime(year, month, 1,0,0,0);
                    end = new DateTime(year, month, 1).AddMonths(1).AddSeconds(-1);
                    break;
                case "w":
                    int i = dtNow.DayOfWeek - DayOfWeek.Monday;
                    if (i == -1) i = 6;// i值 > = 0 ，因为枚举原因，Sunday排在最前，此时Sunday-Monday=-1，必须+7=6。
                    TimeSpan ts = new TimeSpan(i, 0, 0, 0);
                    DateTime cal = dtNow.Subtract(ts);
                    begin = new DateTime(cal.Year, cal.Month, cal.Day, 0, 0, 0);
                    end = new DateTime(cal.Year, cal.Month, cal.Day, 0, 0, 0).AddDays(7).AddSeconds(-1);
                    break;
                case "d":
                    begin = new DateTime(year, month, day,0,0,0);
                    end = new DateTime(year, month, day,0,0,0).AddDays(1).AddSeconds(-1);
                    break;
                case "H":
                    begin = new DateTime(year, month, day,hour,0,0);
                    end = new DateTime(year, month, day,hour,0,0).AddHours(1).AddSeconds(-1);
                    break;
                default:
                    break;
            };
            string tableName = _tableNameOrPrefix + "_" + begin.ToString("yyyyMMddHHmm") + "_" + end.ToString("yyyyMMddHHmm");
            tempCahce[tableName] = new ExternalStorageRecord()
            {
                ExternalTableName = tableName,
                TableNamePrefix = _tableNameOrPrefix,
                StartTime = begin,
                EndTime = end
            };
            return tableName;
        }

        public List<string> getRelativeTableName(string param)
        {
            throw new NotImplementedException();
        }

        public Dictionary<string, List<TEntity>> getExtTableName<TEntity>(List<TEntity> models) where TEntity : DGBase, new()
        {
            Dictionary<string, List<TEntity>> dict = new Dictionary<string, List<TEntity>>();
            models.ForEach(
                model =>
                {
                    string tableName =  getExtTableName(model.GetValue(configParam.TimeProperty).ToString());
                    if (!dict.ContainsKey(tableName))
                    {
                        dict[tableName] = new List<TEntity>();
                    }
                    dict[tableName].Add(model);
                });
            return dict;
        }


        public List<string> getAllExtTableNameByParam(string param)
        {
            string tP = configParam.TimeProperty;
            if ((param == null) || (param.IndexOf("["+ tP + "]") == -1))
            {
                return getAllExtTableName();
            }
            else
            {
                string sql = "";
                string deal = param.Replace("(", "").Replace(")", "");
                List<string> list = deal.Split(new[] { "and" }, StringSplitOptions.None).ToList().Where(x => x.IndexOf("[" + tP + "]") != -1).ToList();
                string s1 = "";
                string s2 = "";
                list.ForEach(x =>
                {
                    if (x.IndexOf(">") > -1)
                    {
                        s1 = string.Format("(({0})and ({1}))", x.Replace(tP, "StartTime").Replace("=", "").Replace(">", "<"),
                            x.Replace(tP, "EndTime").Replace("=", "").Replace(">", "<"));
                    }
                    else
                    {
                        s2 = string.Format("(({0})and ({1}))", x.Replace(tP, "StartTime").Replace("=", "").Replace("<", ">"),
                            x.Replace(tP, "EndTime").Replace("=", "").Replace("<", ">"));
                    }
                });
                string subWhere = string.Format("(not(({0}) or ({1})))",s1,s2);
                sql = string.Format("select * from [Project_ExternalStorageRecord]  where (([TableNamePrefix]='{0}') and {1}) order by ID desc", _tableNameOrPrefix, subWhere);
                return DoSQL(sql);
            }
        }
        public List<string> DoSQL(string sql)
        {
            List<string> list = new List<string>();
            using (SqlConnection conn = new SqlConnection(_SQLConn.getConnectionStr()))
            {
                conn.Open();
                using (SqlCommand sqlCommand = new SqlCommand(sql, conn))
                {
                    sqlCommand.CommandTimeout = 300;
                    SqlDataReader sqlDataReader = sqlCommand.ExecuteReader();
                    DataTable dataTable = new DataTable();
                    dataTable.Load(sqlDataReader);
                    sqlDataReader.Close();

                    if (dataTable.Rows.Count > 0)
                    {
                        for (int i = 0; i < dataTable.Rows.Count; i++)
                        {
                            list.Add(dataTable.Rows[i]["ExternalTableName"].ToString());
                        }

                    }
                    return list;
                }
            }
        }
        public List<string> getAllExtTableName()
        {
            List<string> list = new List<string>();
            string sql = string.Format("select * from [Project_ExternalStorageRecord] where ([TableNamePrefix]='{0}') order by ID desc ", _tableNameOrPrefix);
            return DoSQL(sql);
        }
        public ExternalStorageRecord recordCreatingTable(string tableName)
        {
            if (tempCahce.ContainsKey(tableName))
            {
                return tempCahce[tableName];
 
            }
            else
            {
                return null;
            }
        }


    }
}
